﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MethodWorx.CMS.Configuration;
using MethodWorx.CMS.Plugins;
using MethodWorx.CMS.Content;
using MethodWorx.Core.DomainModel;

namespace MethodWorx.CMS.UI.Models
{
    public class ConfigurePropertiesModel
    {
        public Page Page { get; set;  }
        public ContentItem ContentItem { get; set; }
        public IEnumerable<PageTemplate> Templates { get; set; }

        public ConfigurePropertiesModel(PageTemplate pageTemplate, int selectedPropertyIndex)
            : this(pageTemplate, selectedPropertyIndex, false)
        {
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(Page page, int selectedPropertyIndex, bool includeParents) :
            this(page.Template, selectedPropertyIndex, includeParents)
        {
            this.Page = page;
            
            foreach (var property in page.Properties)
            {
                var pd = this.Properties.FirstOrDefault(p => p.Name == property.Name);
                //  only if the types match can we update
                if (pd != null && pd.Custom.GetType() == property.Value.GetType())
                {
                    ((ICustomPropertyDetails)pd.Custom).CopyValueFrom((ICustomPropertyDetails)property.Value);
                }
            }
            this.ShowGrouping = true;
        }

       

        public ConfigurePropertiesModel(Page page, int selectedPropertyIndex, bool includeParents, string name) :
            this(page.Template, selectedPropertyIndex, includeParents, name)
        {
            this.Page = page;
            
            foreach (var property in page.Properties)
            {
                var pd = this.Properties.FirstOrDefault(p => p.Name == property.Name);
                //  only if the types match can we update
                if (pd != null && pd.Custom.GetType() == property.Value.GetType())
                {
                    ((ICustomPropertyDetails)pd.Custom).CopyValueFrom((ICustomPropertyDetails)property.Value);
                }
            }
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(PageTemplate pageTemplate, int selectedPropertyIndex, bool includeParents)
            : this(pageTemplate, selectedPropertyIndex, includeParents, null)
        {
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(PageTemplate pageTemplate, int selectedPropertyIndex, bool includeParents, string name)
        {
            this.Properties = new PropertyDetails<object>[] { };
            this.SelectedPropertyIndex = selectedPropertyIndex;
            this.PageTemplate = pageTemplate;
            
            var properties = this.Properties.ToList();
            int index = 0;
            while (pageTemplate != null)
            {
                foreach (var property in pageTemplate.Properties.OrderBy(p => p.Index).Where(p => name == null || p.Name == name))
                {
                    properties.Add(new PropertyDetails<object>()
                    {
                        Name = property.Name,
                        Type = property.Type,
                        Mandatory = property.Mandatory,
                        Index = index,
                        Custom = property.Custom.Clone(),
                        Group = property.Group
                    });
                    index ++;
                }
                // seperate the properties
                if (includeParents)
                    pageTemplate = pageTemplate.Parent;
                else
                    break;
            }
            this.Properties = properties.ToArray();
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(int selectedPropertyIndex)
        {
            this.Properties = new PropertyDetails<object>[] { };
            this.SelectedPropertyIndex = selectedPropertyIndex;
            this.ShowGrouping = true;
        }


        public ConfigurePropertiesModel(ContentItem contentItem, int selectedPropertyIndex) 
            : this(contentItem.Template, selectedPropertyIndex)
        {
            this.ContentItem = contentItem;
            foreach (var property in contentItem.Properties)
            {
                var pd = this.Properties.FirstOrDefault(p => p.Name == property.Name);
                //  only if the types match can we update
                if (pd != null && pd.Custom.GetType() == property.Value.GetType())
                {
                    ((ICustomPropertyDetails)pd.Custom).CopyValueFrom((ICustomPropertyDetails)property.Value);
                }
            }
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(ContentItem contentItem, int selectedPropertyIndex, string name) :
            this(contentItem.Template, selectedPropertyIndex, name)
        {
            this.ContentItem = contentItem;
            foreach (var property in contentItem.Properties)
            {
                var pd = this.Properties.FirstOrDefault(p => p.Name == property.Name);
                //  only if the types match can we update
                if (pd != null && pd.Custom.GetType() == property.Value.GetType())
                {
                    ((ICustomPropertyDetails)pd.Custom).CopyValueFrom((ICustomPropertyDetails)property.Value);
                }
            }
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(ContentTemplate contentTemplate, int selectedPropertyIndex)
        {
            this.Properties = new PropertyDetails<object>[] { };
            this.SelectedPropertyIndex = selectedPropertyIndex;
            this.ContentTemplate = contentTemplate;

            var properties = this.Properties.ToList();
            foreach (var property in this.ContentTemplate.Properties.OrderBy(p => p.Index))
            {
                properties.Add(new PropertyDetails<object>()
                {
                    Name = property.Name,
                    Type = property.Type,
                    Mandatory = property.Mandatory,
                    Index = property.Index,
                    Custom = property.Custom.Clone()
                });
            }
            this.Properties = properties.ToArray();
            this.ShowGrouping = true;
        }

        public ConfigurePropertiesModel(ContentTemplate contentTemplate, int selectedPropertyIndex, string name)
        {
            this.Properties = new PropertyDetails<object>[] { };
            this.SelectedPropertyIndex = selectedPropertyIndex;
            this.ContentTemplate = contentTemplate;

            var properties = this.Properties.ToList();
            var index = 0;
            foreach (var property in this.ContentTemplate.Properties.OrderBy(p => p.Index).Where(c => c.Name == name))
            {
                properties.Add(new PropertyDetails<object>()
                {
                    Name = property.Name,
                    Type = property.Type,
                    Mandatory = property.Mandatory,
                    Index = index,
                    Custom = property.Custom.Clone()
                });

                index++;
            }
            this.Properties = properties.ToArray();
            this.ShowGrouping = true;
        }

  


        public PropertyDetails<object>[] Properties
        {
            get;
            set;
        }

        public int SelectedPropertyIndex { get; private set; }
        public ContentTemplate ContentTemplate { get; private set; }
        public PageTemplate PageTemplate { get; private set; }
        public bool ShowGrouping { get; set; }

        public void Add()
        {
            var properties = this.Properties.ToList();

            properties.Add(new PropertyDetails<object>()
                {
                    Name = "NewProperty",
                    Type = "Plain Text",
                    Mandatory = false,
                    Index = Properties.Length,
                    Custom = new PlainTextPropertyDetails()
                });
            this.Properties = properties.ToArray();
        }

        public SelectList GetPropertyTypeSelectList(PropertyDetails<object> property)
        {
            var items = new PropertyConfiguration().GetPropertyConfigurations().Select(pc => pc.Name);

            return new SelectList(items, property.Type);
        }

        public void Remove(int index)
        {
            this.Properties = this.Properties.Where(p => p.Index != index).ToArray();
        }
    }
}